<template>
  <div class="websocket-client module-container">
    <div class="module-header">
      <h2>WebSocket 客户端</h2>
      <p class="module-description">WebSocket 连接测试和调试工具</p>
    </div>

    <div class="module-content">
      <el-card class="connection-card">
        <div class="connection-bar">
          <el-input
            v-model="url"
            placeholder="ws://localhost:8080/websocket"
            :disabled="isConnected"
          >
            <template slot="prepend">
              <el-select v-model="protocol" style="width: 80px" :disabled="isConnected">
                <el-option label="ws://" value="ws" />
                <el-option label="wss://" value="wss" />
              </el-select>
            </template>
          </el-input>
          
          <el-button
            v-if="!isConnected"
            type="primary"
            @click="connect"
          >
            连接
          </el-button>
          <el-button
            v-else
            type="danger"
            @click="disconnect"
          >
            断开
          </el-button>
          
          <ConnectionStatus :connected="isConnected" :connecting="isConnecting" />
        </div>
      </el-card>

      <el-row :gutter="20" style="margin-top: 20px">
        <el-col :span="12">
          <el-card>
            <div slot="header">
              <span>发送消息</span>
            </div>
            
            <el-input
              type="textarea"
              v-model="sendMessage"
              :rows="10"
              placeholder="输入要发送的消息..."
              :disabled="!isConnected"
            />
            
            <div class="send-options">
              <el-radio-group v-model="messageType">
                <el-radio label="text">文本</el-radio>
                <el-radio label="json">JSON</el-radio>
                <el-radio label="binary">二进制</el-radio>
              </el-radio-group>
              
              <div>
                <el-button @click="formatJson" :disabled="messageType !== 'json'">
                  格式化
                </el-button>
                <el-button
                  type="primary"
                  @click="send"
                  :disabled="!isConnected"
                >
                  发送
                </el-button>
              </div>
            </div>
          </el-card>
        </el-col>

        <el-col :span="12">
          <el-card>
            <div slot="header" class="messages-header">
              <span>接收消息</span>
              <div>
                <el-checkbox v-model="autoScroll">自动滚动</el-checkbox>
                <el-button size="mini" @click="clearMessages">清空</el-button>
              </div>
            </div>
            
            <div class="messages-container" ref="messagesContainer">
              <div
                v-for="msg in messages"
                :key="msg.id"
                class="message-item"
                :class="msg.type"
              >
                <div class="message-meta">
                  <el-tag size="mini" :type="msg.type === 'sent' ? 'success' : 'info'">
                    {{ msg.type === 'sent' ? '发送' : '接收' }}
                  </el-tag>
                  <span class="message-time">{{ formatTime(msg.timestamp) }}</span>
                </div>
                <pre class="message-content">{{ msg.content }}</pre>
              </div>
              
              <div v-if="messages.length === 0" class="empty-messages">
                <i class="el-icon-chat-line-round"></i>
                <p>暂无消息</p>
              </div>
            </div>
          </el-card>
        </el-col>
      </el-row>

      <el-card style="margin-top: 20px">
        <div slot="header">
          <span>连接信息</span>
        </div>
        
        <el-descriptions :column="3" border>
          <el-descriptions-item label="状态">
            <el-tag :type="statusType" size="small">{{ statusText }}</el-tag>
          </el-descriptions-item>
          <el-descriptions-item label="连接时间">
            {{ connectedAt || '-' }}
          </el-descriptions-item>
          <el-descriptions-item label="消息统计">
            发送: {{ sentCount }} / 接收: {{ receivedCount }}
          </el-descriptions-item>
          <el-descriptions-item label="协议">
            {{ protocol }}
          </el-descriptions-item>
          <el-descriptions-item label="URL">
            {{ fullUrl || '-' }}
          </el-descriptions-item>
          <el-descriptions-item label="延迟">
            {{ latency }}ms
          </el-descriptions-item>
        </el-descriptions>
      </el-card>
    </div>
  </div>
</template>

<script>
import ConnectionStatus from '@/components/ConnectionStatus.vue'

export default {
  name: 'WebSocket',
  components: {
    ConnectionStatus
  },
  data() {
    return {
      protocol: 'ws',
      url: 'localhost:8080/websocket',
      ws: null,
      isConnected: false,
      isConnecting: false,
      status: 'disconnected',
      sendMessage: '',
      messageType: 'text',
      messages: [],
      autoScroll: true,
      connectedAt: null,
      sentCount: 0,
      receivedCount: 0,
      latency: 0,
      pingInterval: null
    }
  },
  computed: {
    fullUrl() {
      return this.url ? `${this.protocol}://${this.url}` : ''
    },
    
    statusText() {
      const statusMap = {
        disconnected: '未连接',
        connecting: '连接中',
        connected: '已连接',
        error: '连接错误'
      }
      return statusMap[this.status]
    },
    
    statusType() {
      const typeMap = {
        disconnected: 'info',
        connecting: 'warning',
        connected: 'success',
        error: 'danger'
      }
      return typeMap[this.status]
    }
  },
  methods: {
    connect() {
      if (this.ws) {
        this.ws.close()
      }
      
      this.status = 'connecting'
      this.isConnecting = true
      
      try {
        this.ws = new WebSocket(this.fullUrl)
        
        this.ws.onopen = () => {
          this.status = 'connected'
          this.isConnected = true
          this.isConnecting = false
          this.connectedAt = new Date().toLocaleString()
          this.$message.success('WebSocket 连接成功')
          this.startPing()
        }
        
        this.ws.onmessage = (event) => {
          this.receivedCount++
          this.addMessage('received', event.data)
        }
        
        this.ws.onerror = (error) => {
          this.status = 'error'
          this.isConnecting = false
          this.$message.error('WebSocket 连接错误')
          console.error('WebSocket error:', error)
        }
        
        this.ws.onclose = () => {
          this.status = 'disconnected'
          this.isConnected = false
          this.isConnecting = false
          this.connectedAt = null
          this.stopPing()
          this.$message.info('WebSocket 连接已关闭')
        }
      } catch (error) {
        this.status = 'error'
        this.$message.error('创建 WebSocket 连接失败: ' + error.message)
      }
    },
    
    disconnect() {
      if (this.ws) {
        this.ws.close()
        this.ws = null
      }
      this.isConnecting = false
    },
    
    send() {
      if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
        this.$message.warning('WebSocket 未连接')
        return
      }
      
      if (!this.sendMessage) {
        this.$message.warning('请输入消息内容')
        return
      }
      
      let message = this.sendMessage
      
      if (this.messageType === 'json') {
        try {
          JSON.parse(message)
        } catch (e) {
          this.$message.error('JSON 格式错误')
          return
        }
      }
      
      this.ws.send(message)
      this.sentCount++
      this.addMessage('sent', message)
    },
    
    formatJson() {
      try {
        const parsed = JSON.parse(this.sendMessage)
        this.sendMessage = JSON.stringify(parsed, null, 2)
      } catch (e) {
        this.$message.error('JSON 格式错误')
      }
    },
    
    addMessage(type, content) {
      this.messages.push({
        id: Date.now() + Math.random(),
        type,
        content,
        timestamp: new Date()
      })
      
      if (this.messages.length > 100) {
        this.messages = this.messages.slice(-100)
      }
      
      if (this.autoScroll) {
        this.$nextTick(() => {
          const container = this.$refs.messagesContainer
          if (container) {
            container.scrollTop = container.scrollHeight
          }
        })
      }
    },
    
    clearMessages() {
      this.messages = []
      this.sentCount = 0
      this.receivedCount = 0
    },
    
    formatTime(timestamp) {
      return new Date(timestamp).toLocaleTimeString()
    },
    
    startPing() {
      this.pingInterval = setInterval(() => {
        if (this.ws && this.ws.readyState === WebSocket.OPEN) {
          const start = Date.now()
          this.ws.send('ping')
          setTimeout(() => {
            this.latency = Date.now() - start
          }, 100)
        }
      }, 5000)
    },
    
    stopPing() {
      if (this.pingInterval) {
        clearInterval(this.pingInterval)
        this.pingInterval = null
      }
    }
  },
  beforeDestroy() {
    this.disconnect()
  }
}
</script>

<style lang="scss" scoped>
@import '../../styles/variables.scss';

.websocket-client {
  .module-content {
    padding: $spacing-large;
  }
  
  .connection-card {
    .connection-bar {
      display: flex;
      gap: $spacing-base;
      align-items: center;
    }
  }
  
  .send-options {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: $spacing-medium;
  }
  
  .messages-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  
  .messages-container {
    height: 400px;
    overflow: auto;
    background: #f5f5f5;
    border-radius: 4px;
    padding: $spacing-base;
    
    .message-item {
      background: #fff;
      border-radius: 4px;
      padding: $spacing-base;
      margin-bottom: $spacing-base;
      
      &.sent {
        border-left: 3px solid $success-color;
      }
      
      &.received {
        border-left: 3px solid $info-color;
      }
      
      .message-meta {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: $spacing-small;
        
        .message-time {
          color: $text-secondary;
          font-size: $font-size-small;
        }
      }
      
      .message-content {
        margin: 0;
        font-family: monospace;
        font-size: 12px;
        white-space: pre-wrap;
        word-wrap: break-word;
      }
    }
    
    .empty-messages {
      text-align: center;
      padding: $spacing-extra-large;
      color: $text-secondary;
      
      i {
        font-size: 48px;
        margin-bottom: $spacing-medium;
      }
    }
  }
}
</style>